#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include "lwip/ip4_addr.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"

static int g_connectSuccess = 0;
static int g_ssid_count = 0;
static int g_staScanSuccess = 0;

int WaitConnectResult(void);
void WaitScanResult(void);
void onStaJoinHandle(StationInfo *info);
void onStaLeaveHandle(StationInfo *info);
void onStaChangedHandle(int state, int size);
void OnWifiConnectionChangedHandle(int state, WifiLinkedInfo *info);
void OnWifiScanStateChangedHandle(int state, int size);
int WifiConnect(const char *ssid,const char*pwd){
    static struct netif *g_lwip = NULL;
    sleep(2);
    WifiEvent wevent = {0};
    WifiDeviceConfig wconfig = {0};
    wevent.OnHotspotStaJoin = onStaJoinHandle;
    wevent.OnHotspotStaLeave = onStaLeaveHandle;
    wevent.OnHotspotStateChanged = onStaChangedHandle;
    wevent.OnWifiConnectionChanged = OnWifiConnectionChangedHandle;
    wevent.OnWifiScanStateChanged = OnWifiScanStateChangedHandle;
    WifiErrorCode err = RegisterWifiEvent(&wevent);
    if(err !=WIFI_SUCCESS) {
        printf("Register Failed  Error = %d\n",err);
        return ;
    }
    printf("Register Wifi Success\n");
    
    err = EnableWifi();
    if(err !=WIFI_SUCCESS) {
        printf("Enable Failed  Error = %d\n",err);
        return ;
    }
    printf("EnableWifi Success\n");
    if(IsWifiActive() == 0){
        printf("WifiActive Failed\n");
        return ;
    }

    WifiScanInfo *info = NULL;
    info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
    if(info == NULL){
        printf("Malloc Error\n");
        return ;
    }
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
    do{
        g_ssid_count = 0;
        g_staScanSuccess = 0;
        Scan();
        WaitScanResult();
        GetScanInfoList(info,&size);

    }while (g_staScanSuccess != 1);
    for(int i = 0;i <g_ssid_count;i++){
        printf("No = %d,Ssid = %-30s,rssi = %d\r\n",i+1,info[i].ssid,info[i].rssi / 100);
    }
    for(int i = 0;i < g_ssid_count;i++){
        if(strcmp(ssid,info[i].ssid) == 0){
            int result;
            strcpy(wconfig.ssid,info[i].ssid);
            strcpy(wconfig.preSharedKey,pwd);
            wconfig.securityType = WIFI_SEC_TYPE_PSK;
            if(AddDeviceConfig(&wconfig,&result) == WIFI_SUCCESS){
                if(ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1){
                    printf("Wifi Connect Success\n");
                    g_lwip = netifapi_netif_find("wlan0");
                    break;
                }
            }
        }
        if(i == g_ssid_count -1){
            printf("Error:No Wifi As Expected \n");
            while(1){
                sleep(1);
            }
        }
    }
    printf("==================================\n");
    //启动DHCP
    if(g_lwip){
        dhcp_start(g_lwip);
        printf("begin to dhcp\n");
    }
    for(;;){
        if(dhcp_is_bound(g_lwip) == ERR_OK){
            printf("DHCP State Ok\n");
            netifapi_netif_common(g_lwip,dhcp_clients_info_show,NULL);
            break;
        }
        printf("DHCP State :inprogress\n");
        sleep(1);   
    }
    return 1;
}
int WaitConnectResult(){
    int scanTimeout = 15;
    while(scanTimeout > 0){
        sleep(1);
        scanTimeout --;
        if(g_connectSuccess == 1){
            printf("WaitConnectionResult: Wait Success[%d]s\n",15 - scanTimeout);
            return 1;
        }
    }
    printf("WaitConnectionResult: TimeOut \n");
    return 0;
}
void WaitScanResult(){
    int scanTimeout = 15;
    while(scanTimeout > 0){
        sleep(1);
        scanTimeout --;
        if(g_staScanSuccess == 1){
            printf("WaitScanResult: Wait Success[%d]s\n",15 - scanTimeout);
            return;
        }
    }
    printf("WaitScanResult: TimeOut \n");
}
void onStaJoinHandle(StationInfo *info){
    if(info == NULL) printf("===WARNING NOT EXIST===\n");
    else {
        char macAddress[33] = {0};
        unsigned char *mac = info->macAddress;
        snprintf_s(macAddress,sizeof(macAddress),sizeof(macAddress) - 1,"%02x:%02x:%02x:%02x:%02x:%02x",
        mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
        printf("StaJoin Mac:%s,reason:%d\n",macAddress,info->disconnectedReason);
    }
}
void onStaLeaveHandle(StationInfo *info){
    if(info == NULL) printf("===WARNING NOT EXIST===\n");
    else {
        char macAddress[33] = {0};
        unsigned char *mac = info->macAddress;
        snprintf_s(macAddress,sizeof(macAddress),sizeof(macAddress) - 1,"%02x:%02x:%02x:%02x:%02x:%02x",
        mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
        printf("StaJoin Mac:%s,reason:%d\n",macAddress,info->disconnectedReason);
    }
}
void onStaChangedHandle(int state, int size){
    printf("StateChanged state = %d,size = %d\n",state,size);
}
void OnWifiConnectionChangedHandle(int state, WifiLinkedInfo *info){
    if(state > 0){
        g_connectSuccess = 1;
        printf("Wifi Connect Ok\n");
    }
    else {
        g_connectSuccess = 0;
        printf("Wifi Connect Failed,Please Check\n");
    }
}
void OnWifiScanStateChangedHandle(int state, int size){
    if(size > 0){
        g_ssid_count = size;
        g_staScanSuccess = 1;
        printf("Callback Function For Wifi Scan:state = %d size = %d\n",state,size);
    }
}